/**
 * Copyright (c) 2012, Camelot and/or its affiliates. All rights reserved.
 * Camelot PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
 */

package com.camelot.ccr.global.dao;

import java.io.Serializable;
import java.util.Collection;
import java.util.List;
import java.util.Map;

import org.hibernate.Criteria;
import org.hibernate.Query;
import org.hibernate.SQLQuery;
import org.hibernate.Session;
import org.hibernate.criterion.Order;
import org.springframework.dao.DataAccessException;

import com.camelot.ccr.global.util.Pager;

/**
 * <pre>
 * 泛型dao模式
 * </pre>
 * 
 * @param <T>
 *            泛型类
 * @param <ID>
 *            泛型主键
 * @author Liu Jun
 * @version V0.1, 2013-12-26 下午2:21:49
 */
public interface GenericDaO<T, ID extends Serializable> {

	/**
	 * <pre>
	 * 获得session
	 * </pre>
	 * 
	 * @return 当前线程session
	 * @author Liu Jun, 2013-12-26 下午2:22:05
	 */
	Session getCurrentSession();

	/**
	 * <pre>
	 * 保存对象实体
	 * </pre>
	 * 
	 * @param t
	 *            泛型实体
	 * @throws DataAccessException
	 *             数据库异常
	 * @author Liu Jun, 2013-12-26 下午2:22:36
	 */
	void save(T t) throws DataAccessException;

	/**
	 * <pre>
	 * 根据对象，对象有ID此对象
	 * </pre>
	 * 
	 * @param t
	 *            泛型实体
	 * @throws DataAccessException
	 *             数据库异常
	 * @author Liu Jun, 2013-12-26 下午2:22:45
	 */
	void delete(T t) throws DataAccessException;

	/**
	 * <pre>
	 * 根据ID获取对象. 实际调用Hibernate的session.get()方法
	 * </pre>
	 * @param <T> 泛型實體
	 * @param id
	 *            主键ID
	 * @return 泛型实体
	 * @throws DataAccessException
	 *             数据库异常
	 * @author Liu Jun, 2013-12-26 下午2:23:49
	 */
	<T> T get(final ID id) throws DataAccessException;

	/**
	 * <pre>
	 * 获取全部对象
	 * </pre>
	 * @param <T> 泛型實體
	 * @return 所有对象
	 * @throws DataAccessException
	 *             数据库异常
	 * @author Liu Jun, 2013-12-26 下午2:24:01
	 */
	<T> List<T> getAll() throws DataAccessException;

	/**
	 * <pre>
	 * 更新实体
	 * </pre>
	 * 
	 * @param t
	 *            泛型实体
	 * @throws DataAccessException
	 *             数据库异常
	 * @author Liu Jun, 2013-12-26 下午2:24:08
	 */
	void update(T t) throws DataAccessException;
	
	void merge(T t) throws DataAccessException;

	/**
	 * <pre>
	 * 保存或修改实体
	 * </pre>
	 * 
	 * @param t
	 *            泛型实体
	 * @throws DataAccessException
	 *             数据库异常
	 * @author Liu Jun, 2013-12-26 下午2:24:24
	 */
	void saveOrUpdate(T t) throws DataAccessException;

	/**
	 * <pre>
	 * 创建hibernate query 并关联泛型对象
	 * </pre>
	 * 
	 * @param hql
	 *            hql
	 * @return 创建泛型query对象，里面根据泛型类拼成 from clazz ...形式
	 * @throws DataAccessException
	 *             数据库异常
	 * @author Liu Jun, 2013-12-26 下午2:24:37
	 */
	Query createTQuery(final String hql) throws DataAccessException;

	/**
	 * 
	 * <pre>
	 * 生成原生Query
	 * </pre>
	 * 
	 * @param hql
	 *            hql
	 * @return query对象
	 * @throws DataAccessException
	 *             数据库异常
	 * @author Liu Jun, 2013-12-26 下午5:30:08
	 */
	Query createQuery(final String hql) throws DataAccessException;

	/**
	 * <pre>
	 * 创建hibernate sqlquery 查询对象
	 * </pre>
	 * 
	 * @param sql
	 *            sql
	 * @return SQLQuery
	 * @throws DataAccessException
	 *             数据库
	 * @author Liu Jun, 2013-12-26 下午2:24:48
	 */
	SQLQuery createSQLQuery(final String sql) throws DataAccessException;

	/**
	 * <pre>
	 * 创建hibernate sqlquery 查询对象
	 * </pre>
	 * 
	 * @param id
	 *            主键ID
	 * @return 泛型实体
	 * @throws DataAccessException
	 *             数据库异常
	 * @author Liu Jun, 2013-12-26 下午2:24:59
	 */
	T findById(final ID id) throws DataAccessException;

	/**
	 * <pre>
	 * 根据属性返回对象
	 * </pre>
	 * @param <T> 泛型t
	 * @param proName
	 *            属性名称
	 * @param proValue
	 *            属性值
	 * @return 返回满足条件的集合列表
	 * @throws DataAccessException
	 *             数据库异常
	 * @author Liu Jun, 2013-12-26 下午2:27:16
	 */
	<T> List<T> findByProperty(final String proName, final String proValue) throws DataAccessException;

	/**
	 * <pre>
	 * 创建动态查询对象
	 * </pre>
	 * 
	 * @return 动态查询对象
	 * @throws DataAccessException
	 *             数据库异常
	 * @author Liu Jun, 2013-12-26 下午2:28:00
	 */
	Criteria createCriteria() throws DataAccessException;

	/**
	 * <pre>
	 * 查询满足实体参数的列表并分页
	 * </pre>
	 * @param <T> 泛型t
	 * @param exampleEntity
	 *            实体参数，不适用类里有对象关联关系的场景
	 * @param firstResult
	 *            开始条数
	 * @param maxResults
	 *            显示多少条数
	 * @return 满足条件的集合
	 * @throws DataAccessException
	 *             数据库异常
	 * @author Liu Jun, 2013-12-26 下午2:28:10
	 */
	<T> List<T> findByExample(final T exampleEntity, final int firstResult, final int maxResults) throws DataAccessException;

	/**
	 * <pre>
	 * 查询满足实体参数的列表
	 * </pre>
	 * @param <T> 泛型t 
	 * @param exampleEntity
	 *            实体参数,不适用类里有对象关联关系的场景
	 * @return 满足条件的集合
	 * @throws DataAccessException
	 *             数据库异常
	 * @author Liu Jun, 2013-12-26 下午2:30:00
	 */
	<T> List<T> findByExample(final T exampleEntity) throws DataAccessException;

	/**
	 * <pre>
	 * 【findByExample】基础上加排序功能，不适用类里有对象关联关系的场景
	 * </pre>
	 * @param <T> 泛型t
	 * @param exampleEntity
	 *            参数模板
	 * @param firstResult
	 *            数据库开始位置
	 * @param maxResults
	 *            每页显示记录数
	 * @param order
	 *            排序参数，自己自定义传值
	 * @return 符合条件的列表
	 * @throws DataAccessException
	 *             数据库异常
	 * @author Liu Jun, 2013-12-26 下午2:30:46
	 */
	<T> List<T> findByExampleOrder(final T exampleEntity, final int firstResult, final int maxResults, Order... order)
		throws DataAccessException;

	/**
	 * <pre>
	 * 泛型本类完全查询方法
	 * </pre>
	 * @param <T> 泛型t 
	 * @param map
	 *            key为属性名，value为属性值
	 * @return 符合条件的列表
	 * @throws DataAccessException
	 *             数据库异常
	 * @author Liu Jun, 2013-12-26 下午2:31:42
	 */
	<T> List<T> findByCondition(final Map<String, Object> map) throws DataAccessException;

	/**
	 * <pre>
	 * 根据类型去调用Quqery或SQLQuery 用？传参
	 * </pre>
	 * 
	 * @param hqlOrSql
	 *            sql或hql语句 带？传参
	 * @param params
	 *            数据值
	 * @param type
	 *            0代表sql 1代表hql
	 * @return 查询如何提交集合
	 * @throws DataAccessException
	 *             数据库异常
	 * @author Liu Jun, 2013-12-26 下午10:26:51
	 */
	List<?> find(final String hqlOrSql, Collection<?> params, int type) throws DataAccessException;;

	/**
	 * <pre>
	 * hql查询满足条件的列表,用？传参
	 * </pre>
	 * 
	 * @param hql
	 *            用？传参
	 * @param params
	 *            参数值
	 * @return List
	 * @throws DataAccessException
	 *             数据库异常
	 * @author Liu Jun, 2013-12-26 下午2:32:09
	 */
	List<?> findByHQL(final String hql, Collection<?> params) throws DataAccessException;

	/**
	 * <pre>
	 * sql查询满足条件的列表
	 * </pre>
	 * 
	 * @param sql
	 *            sql
	 * @param params
	 *            参数值
	 * @return List
	 * @throws DataAccessException
	 *             数据库异常
	 * @author Liu Jun, 2013-12-26 下午2:32:09
	 */
	List<?> findBySQL(final String sql, Collection<?> params) throws DataAccessException;

	/**
	 * <pre>
	 * 更新hql语句
	 * </pre>
	 * 
	 * @param updateHql
	 *            修改的hql语句
	 * @param values
	 *            需要修改的字段和值放到map中
	 * @return 更新记录数
	 * @throws DataAccessException
	 *             数据库异常
	 * @author Liu Jun, 2013-12-26 下午2:32:56
	 */
	int updateByHql(final String updateHql, final Map<String, Object> values) throws DataAccessException;

	/**
	 * <pre>
	 * 执行原生sql语句
	 * </pre>
	 * 
	 * @param updateSql
	 *            要执行的sql语句
	 * @param values
	 *            参数列表
	 * @return 结果条数
	 * @throws DataAccessException
	 *             数据库异常
	 * @author Liu Jun, 2013-12-26 下午2:33:25
	 */
	int updateBySql(final String updateSql, final Map<String, Object> values) throws DataAccessException;

	/**
	 * <pre>
	 * 批量删除实体
	 * </pre>
	 * 
	 * @param entities
	 *            泛型实体集合
	 * @throws DataAccessException
	 *             数据库异常
	 * @author Liu Jun, 2013-12-26 下午2:34:05
	 */
	void deleteAll(final Collection<T> entities) throws DataAccessException;

	/**
	 * <pre>
	 * 分页查询
	 * </pre>
	 * @param <T> 泛型t 
	 * @param hql
	 *            查询的条件的追加语句
	 * @param firstResult
	 *            数据库开始位置
	 * @param maxResult
	 *            每页显示记录数
	 * @return List
	 * @throws DataAccessException
	 *             数据库异常
	 * @author Liu Jun, 2013-12-26 下午2:34:27
	 */
	<T> List<T> queryListPage(String hql, int firstResult, int maxResult) throws DataAccessException;

	/**
	 * 
	 * <pre>
	 * 获取记录条数
	 * </pre>
	 * 
	 * @return 总记录数
	 * @throws DataAccessException
	 *             数据库异常
	 * @author Liu Jun, 2013-12-26 下午2:34:54
	 */
	Long countEntity() throws DataAccessException;

	/**
	 * <pre>
	 * 查询总记录数
	 * </pre>
	 * 
	 * @param hql
	 *            hql语句
	 * @param values
	 *            key为属性 value为值
	 * @return 返回总记录数
	 * @throws DataAccessException
	 *             数据库异常
	 * @author Liu Jun, 2013-12-26 下午4:55:24
	 */
	Long countEntity(final String hql, final Map<String, Object> values) throws DataAccessException;

	/**
	 * <pre>
	 * 查询总记录数
	 * </pre>
	 * 
	 * @param hql
	 *            hql语句
	 * @param values
	 *            参数值
	 * @return 返回总记录数
	 * @throws DataAccessException
	 *             数据库异常
	 * @author Liu Jun, 2013-12-26 下午4:55:24
	 */
	Long countEntityByHql(final String hql, final Collection<?> values) throws DataAccessException;

	/**
	 * <pre>
	 * 查询总记录数
	 * </pre>
	 * 
	 * @param sql
	 *            sql语句
	 * @param values
	 *            参数值
	 * @return 返回总记录数
	 * @throws DataAccessException
	 *             数据库异常
	 * @author Liu Jun, 2013-12-26 下午4:55:24
	 */
	Long countEntityBySql(final String sql, final Collection<?> values) throws DataAccessException;

	/**
	 * <pre>
	 * 查询总记录数
	 * </pre>
	 * 
	 * @param hqlOrSql
	 *            hql 或sql 语句 关键字都小写例如：select from 等
	 * @param values
	 *            参数值
	 * @param type
	 *            0代表sql 1代表hql
	 * @return 返回总记录数
	 * @throws DataAccessException
	 *             数据库异常
	 * @author Liu Jun, 2013-12-26 下午4:55:24
	 */
	Long countEntity(final String hqlOrSql, final Collection<?> values, int type) throws DataAccessException;

	/**
	 * <pre>
	 * 使用sql查询 总数
	 * </pre>
	 * @param hqlOrSql sql语句
	 * @param values 值
	 * @return 总数
	 * @throws DataAccessException 异常信息
	 * @author dengzongyu, 2014年3月18日 下午3:54:07
	 */
    Long countMapEntity(String hqlOrSql, Collection<?> values) throws DataAccessException;
	
	/**
	 * <pre>
	 * hql 分页查询
	 * </pre>
	 * 
	 * @param hql
	 *            hql
	 * @param values
	 *            参数键和参数值
	 * @param curpage
	 *            当前页
	 * @param pagesize
	 *            当页显示条数
	 * @return 返回分页对象
	 * @throws DataAccessException
	 *             数据库异常
	 * @author Liu Jun, 2013-12-26 下午5:48:46
	 */
	Pager<?> queryListPageByHql(final String hql, final Map<String, Object> values, final int curpage, final int pagesize)
		throws DataAccessException;

	/**
	 * <pre>
	 * hql 分页查询
	 * </pre>
	 * 
	 * @param hqlOrSql
	 *            hql或sql语句
	 * @param values
	 *            替换？类型的参数值
	 * @param curpage
	 *            当前页
	 * @param pagesize
	 *            当前页条数
	 * @param type
	 *            0代表sql 1代表hql
	 * @return 返回分页对象
	 * @throws DataAccessException
	 *             数据库异常
	 * @author Liu Jun, 2013-12-26 下午5:48:46
	 */
	Pager<?> queryListPage(final String hqlOrSql, final int curpage, 
		final int pagesize, final Collection<?> values, int type)throws DataAccessException;

	/**
	 * <pre>
	 * hql 分页查询
	 * </pre>
	 * 
	 * @param hql
	 *            hql
	 * @param values
	 *            替换？的参数值
	 * @param curpage
	 *            当前页
	 * @param pagesize
	 *            当前条数
	 * @return 返回分页对象
	 * @throws DataAccessException
	 *             数据库异常
	 * @author Liu Jun, 2013-12-26 下午5:48:46
	 */
	Pager<?> queryListPageByHql(final String hql, final int curpage, final int pagesize, final Collection<?> values)
		throws DataAccessException;

	/**
	 * <pre>
	 * hql 分页查询
	 * </pre>
	 * 
	 * @param hql
	 *            hql
	 * @param pager
	 *            分页对象
	 * @param values
	 *            替换?的参数值
	 * @return 分页对象
	 * @throws DataAccessException
	 *             数据库异常
	 * @author Liu Jun, 2013-12-26 下午7:11:27
	 */
	Pager<?> queryListPageByHql(final String hql, Pager<?> pager, final Collection<?> values) throws DataAccessException;

	/**
	 * <pre>
	 * sql 分页查询
	 * </pre>
	 * 
	 * @param sql
	 *            sql
	 * @param values
	 *            替换？的参数值
	 * @param curpage
	 *            当前页
	 * @param pagesize
	 *            当前页显示条数
	 * @return 返回分页对象
	 * @throws DataAccessException
	 *             数据库异常
	 * @author Liu Jun, 2013-12-26 下午5:48:46
	 */
	Pager<?> queryListPageBySql(final String sql, final int curpage, final int pagesize, final Collection<?> values)
		throws DataAccessException;

	/**
	 * <pre>
	 * sql 分页查询
	 * </pre>
	 * 
	 * @param sql
	 *            sql
	 * @param pager
	 *            分页对象
	 * @param values
	 *            替换？的参数值
	 * @return 分页对象
	 * @author Liu Jun, 2013-12-26 下午7:11:27
	 */
	Pager<?> queryListPageBySql(final String sql, Pager<?> pager, final Collection<?> values);

	/**
	 * <pre>
	 * 根据sql语句分页，返回Page<List<Map<String,Object>>>格式数据
	 * </pre>
	 * @param sql sql语句
	 * @param curpage 当前页
	 * @param pagesize 每页记录数
	 * @param values 参数
	 * @return 返回数据
	 * @author chendd, 2014-1-10 上午9:24:32
	 */
	Pager<?> queryListMapPageBySql(final String sql, final int curpage, final int pagesize, Collection<?> values);
	
	/**
	 * <pre>
	 * 根据sql查询一个对象,返回相应的数据
	 * </pre>
	 * @param sql sql语句
	 * @param values 相关参数
	 * @return 返回集合数据
	 * @author chendd, 2014-1-10 下午3:59:46
	 */
	List<Map<String , Object>> queryListMapBySql(String sql , Collection<?> values);

	/**
	 * <pre>
	 * 根据sql查询一个对象,返回相应的数据
	 * </pre>
	 * @param sql sql语句
	 * @param values 可变参数集
	 * @return 返回集合数据
	 * @author chendd, 2014-1-10 下午3:59:46
	 */
	List<Map<String , Object>> queryListMapBySql(String sql , Object... values);
	
	/**
	 * <pre>
	 * 根据sql语句查询实体对象
	 * </pre>
	 * @param sql sql语句
	 * @param values 参数集合
	 * @return 返回查询参数实体
	 * @author chendd, 2014-1-11 上午9:36:23
	 */
	T queryEntityBySql(String sql , Collection<?> values);
	
	/**
	 * <pre>
	 * 根据sql语句查询sql对象
	 * </pre>
	 * @param sql sql语句
	 * @param values 参数对象
	 * @return 返回相关数据，如果没有数据则返回为null
	 * @author chendd, 2014-1-11 上午9:49:55
	 */
	List<T> queryListBySql(String sql , Collection<?> values);
	
	/**
	 * <pre>
	 * 根据sql语句查询sql对象
	 * </pre>
	 * @param sql sql语句
	 * @param values 动态参数集，多个参数以,分割
	 * @return 返回相关数据，如果没有数据则返回为null
	 * @author chendd, 2014-1-11 上午9:49:55
	 */
	List<T> queryListBySql(String sql , Object...params);
	
	/**
	 * <pre>
	 * 查询sql语句
	 * </pre>
	 * @param sql sql语句
	 * @param pageNo 当前页号ss
	 * @param pageSize 每页显示记录数
	 * @param values 查询参数
	 * @return 返回相关分页的数据
	 * @author chendd, 2014-1-11 上午11:12:43
	 */
	Pager<T> queryPageBySql(String sql, int pageNo , int pageSize , Collection<?> values);
	
	/**
	 * <pre>
	 * 查询sql语句
	 * </pre>
	 * @param sql sql语句
	 * @param pageNo 当前页号ss
	 * @param pageSize 每页显示记录数
	 * @param values 动态参数集，多个参数以,分割
	 * @return 返回相关分页的数据
	 * @author chendd, 2014-1-11 上午11:12:43
	 */
	Pager<T> queryPageBySql(String sql, int pageNo , int pageSize , Object... values);
	/**
	 * <pre>
	 * 查询sql语句，参数为集合类
	 * </pre>
	 * @param sql sql
	 * @param values values
	 * @return int
	 * @author Liu Jun, 2014-1-14 上午10:24:28
	 */
	int executeBySql(String sql , Collection<?> values);
	
	/**
	 * 
	 * <pre>
	 * 查询sql语句，参数为集合类
	 * </pre>
	 * @param sql sql语句
	 * @param params 参数集
	 * @return 影响的记录数
	 * @author chendd, 2014-3-17 下午4:15:07
	 */
	int executeBySql(String sql , Object...params);
	/**
	 * <pre>
	 * 批量增加数据
	 * </pre>
	 * @param <T> 泛型类
	 * @param entitys 集合类
	 * @author Liu Jun, 2014-2-20 下午4:51:38
	 */
	<T> void batchSave(List<T> entitys);
	/**
	 * <pre>
	 * 批量更新数据
	 * </pre>
	 * @param <T> 泛型类
	 * @param entitys 集合类
	 * @author Liu Jun, 2014-2-20 下午4:51:38
	 */
	<T> void batchUpdate(List<T> entitys);
	/**
	 * <pre>
	 * 批量删除数据
	 * </pre>
	 * @param <T> 泛型类
	 * @param entitys 集合类
	 * @author Liu Jun, 2014-2-20 下午4:51:38
	 */
	<T> void batchDelete(List<T> entitys);
	
	/**
	 * <pre>
	 * 根据属性名称和属性值获取集合对象
	 * </pre>
	 * @param propertyName 属性名
	 * @param value 属性值
	 * @return 集合数据
	 * @author chendd, 2014-3-1 下午11:03:25
	 */
	List<T> findListByProperty(String propertyName , Object value);
}
